home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Devices / RAMDisk 1.4d5 / RamDRVR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-07  |  14.3 KB  |  495 lines  |  [TEXT/CWIE]

  1. #define __DebugVersion    1
  2. /*
  3. **    Apple Macintosh Developer Technical Support
  4. **
  5. **    RamDRVR.c: Driver for RamDisk Sample
  6. **
  7. **    by Gordon Sheridan and Jim Luther
  8. **  modified incessantly by Brian Bechtel
  9. **  and even more so by Quinn "The Eskimo!"
  10. **
  11. **    File:        RamDRVR.c
  12. **
  13. **    Copyright © 1992-1996 Apple Computer, Inc.
  14. **    All rights reserved.
  15. **
  16. **    You may incorporate this sample code into your applications without
  17. **    restriction, though the sample code has been provided "AS IS" and the
  18. **    responsibility for its operation is 100% yours.  However, what you are
  19. **    not permitted to do is to redistribute the source as "DTS Sample Code"
  20. **    after having made changes. If you're going to re-distribute the source,
  21. **    we require that you make it clear in the source that the code was
  22. **    descended from Apple Sample Code, but that you've made changes.
  23. **
  24. **    Change History (most recent first):
  25. **
  26. **         <1.4>    19970207      Quinn    Reworked to use new file layout and bring generally
  27. **                                    up-to-date.
  28. **        <1.3>    06/20/96    BL°B    Added DriverGestalt, no OLDROUTINENAMES
  29. **                                    detailed comment on driveInfoCC call.
  30. **         <6>    06/10/94    BL°B    Converted to work with Symantec as well.
  31. **         <5>    05/19/94    BL°B    Converted to work with Metrowerks.  Added 
  32. **                                     conditionally compiled main routine for Metrowerks.
  33. **         <4>    10/23/93    JML        Added check for valid globals before accepting
  34. **                                     Prime, Control, or Status calls (except the control
  35. **                                    and status routines that get and set the globals).
  36. **         <3>    10/14/93    JML        Added support for the following Control and Status
  37. **                                    calls: physicalIconCC, mediaIconCC, driveInfoCC,
  38. **                                    formatListSC.  driveStatusSC now returns a copy
  39. **                                    of our DrvQEl.  Prime, Control and Status now checks
  40. **                                    that ioVRefNum = our drive number.  Prime now updates
  41. **                                    dCtlPosition so I/O using fsFromMark will work. All
  42. **                                    debugging code now hidden with "Panic" macros. Prime
  43. **                                    now checks for block aligned I/O (since this is a
  44. **                                    block device).  All calls now return appropriate error
  45. **                                    results.
  46. **        <2+>     7/26/93    gs        Set result = noErr for Status csCode = 8.
  47. **         <2>     6/29/93    gs        Return Drive Stats, miscellaneous clean up.
  48. **         <1>     6/13/93    gs        Allocate space for disk from driver. Clean up comments.
  49. **         <0>     1/17/90    gs        11:58 PM, first version.
  50. **/
  51.  
  52. #ifdef __MWERKS__
  53. #include <A4Stuff.h>
  54. #endif
  55. #ifdef THINK_C
  56. #include <SetupA4.h>
  57. #endif
  58.  
  59. #include <DriverGestalt.h>
  60. #include <Disks.h>
  61.  
  62. #include "RamDiskCommon.h"
  63.  
  64. ///////////////////////////////////////////////////////////////////////////
  65.  
  66. // These should be in <DriverGestalt.h>.
  67.  
  68. enum {
  69.     kdgFlush    = 'flus'                /* Determine if disk driver supports flush and if it needs a flush */
  70. };
  71.  
  72. struct DriverGestaltFlushResponse {
  73.     Boolean     canFlush;                /* Return true if driver supports the */
  74.                                         /* kdcFlush Driver Configure _Control call */
  75.     Boolean     needsFlush;                /* Return true if driver/device has data cached */
  76.                                         /* and needs to be flushed when the disk volume */
  77.                                         /* is flushed by the File Manager */
  78.     UInt8         pad[2];
  79. };
  80. typedef struct DriverGestaltFlushResponse DriverGestaltFlushResponse;
  81.  
  82. enum {
  83.     kdcFlush    = 'flus'                /* Tell a disk driver to flush its cache and any hardware caches */
  84. };
  85.  
  86. #define GetDriverGestaltFlushResponse(p) ((DriverGestaltFlushResponse *)(&((p)->driverGestaltResponse)))
  87.  
  88. ///////////////////////////////////////////////////////////////////////////
  89.  
  90. // These definitely should be a system header file somewhere!
  91.  
  92. enum {
  93.     // Common control codes
  94.     killIOCC            = 1,        /* kill I/O */
  95.     verifyDiskCC        = 5,        /* verify disk */
  96.     formatDiskCC        = 6,        /* format disk */
  97.     ejectDiskCC            = 7,        /* eject disk (ejectable media only) */
  98.     setTagBufferCC        = 8,        /* set tag buffer (.SONY) */
  99.     trackCacheCC        = 9,        /* control track cache (.SONY) */
  100.     physicalIconCC        = 21,        /* return physical location icon and where string */
  101.     mediaIconCC            = 22,        /* return media icon */
  102.     driveInfoCC            = 23,        /* return drive info */
  103.     trackDumpCC            = 18244,    /* diagnostic raw track dump (.SONY) */
  104.  
  105.     // Common status codes
  106.     returnFormatList     = 6,        /* return format list (.SONY) */
  107.     driveStatusSC        = 8            /* drive status */
  108. };
  109.  
  110. ///////////////////////////////////////////////////////////////////////////
  111.  
  112. struct DriverConfigParam {
  113.     QElemPtr     qLink;
  114.     short         qType;
  115.     short         ioTrap;
  116.     Ptr         ioCmdAddr;
  117.     ProcPtr     ioCompletion;
  118.     OSErr         ioResult;
  119.     StringPtr     ioNamePtr;
  120.     short         ioVRefNum;
  121.     short         ioCRefNum;                    /* refNum for I/O operation */
  122.     short         csCode;                        /* == kDriverConfigureCode */
  123.     OSType         driverConfigureSelector;
  124.     UInt32         driverConfigureParameter;
  125. };
  126. typedef struct DriverConfigParam DriverConfigParam;
  127.  
  128. ///////////////////////////////////////////////////////////////////////////
  129.  
  130. // Prototypes for main driver entry points.
  131.  
  132. extern pascal OSErr DRVROpen(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  133. extern pascal OSErr DRVRPrime(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  134. extern pascal OSErr DRVRControl(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  135. extern pascal OSErr DRVRStatus(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  136. extern pascal OSErr DRVRClose(ParmBlkPtr paramBlock, DCtlPtr devCtlEnt);
  137.  
  138. ///////////////////////////////////////////////////////////////////////////
  139.  
  140. pascal OSErr DRVROpen (ParmBlkPtr pb, DCtlPtr dce)
  141. {
  142.     DrvrGlobals       *globe;
  143.     OSErr            result = noErr;
  144.  
  145. #pragma unused (pb)
  146.  
  147.     if (!dce->dCtlStorage)    /* is driver already open ? */
  148.     {
  149.         dce->dCtlStorage = (Handle)NewPtrSysClear(sizeof(DrvrGlobals));
  150.         if (!(Ptr)dce->dCtlStorage)
  151.         {
  152.             result = MemError();
  153.             Panic("\pDRVROpen:NewPtr returned nil");
  154.         }
  155.             
  156.         globe = (DrvrGlobals *)dce->dCtlStorage;
  157.         globe->driveNeedsFlush = false;
  158.     }
  159.     else
  160.         Panic("\pDRVROpen:2nd open attempt");
  161.     
  162.     return (result);
  163. }
  164.  
  165. /*****************************************************************************/
  166.  
  167. pascal OSErr DRVRPrime (ParmBlkPtr pb, DCtlPtr dce)
  168. {
  169.     DrvrGlobals        *globe;
  170.     unsigned long    position;
  171.     unsigned long    count;
  172.     short            calltype;
  173.     OSErr            result;
  174.  
  175.     if (dce->dCtlStorage)
  176.     {
  177.         globe = (DrvrGlobals *)dce->dCtlStorage;
  178.         
  179.         if (globe->driveNumber != 0) /* accept no calls, before the globals are initialized */
  180.         {
  181.             position = dce->dCtlPosition;
  182.             count = pb->ioParam.ioReqCount;
  183.             
  184.             /* Preflight the request for block alignment, size, and range */
  185.             if (((position % 512) == 0) &&
  186.                 ((count % 512) == 0) &&
  187.                 ((count + position) <= globe->ramSize))
  188.             {
  189.                 calltype = 0x00FF & pb->ioParam.ioTrap;
  190.                 switch(calltype)
  191.                 {
  192.                     case aRdCmd:
  193.                         /* Read the data */
  194.                         BlockMoveData(&globe->ramDisk[position], pb->ioParam.ioBuffer, count);
  195.                         break;
  196.                     case aWrCmd:
  197.                         /* Write the data */
  198.                         BlockMoveData(pb->ioParam.ioBuffer, &globe->ramDisk[position], count);
  199.                         globe->driveNeedsFlush = true;
  200.                         break;
  201.                     default:        
  202.                         Panic("\pDRVRPrime: Call wasn't _Read or _Write");
  203.                         break;
  204.                 }
  205.                 
  206.                 dce->dCtlPosition += count;        /* Update the position */
  207.                 pb->ioParam.ioActCount = count;    /* Return the actual count */
  208.                 
  209.                 result = noErr;
  210.             }
  211.             else
  212.             {
  213.                 Panic("\pDRVRPrime: Invalid block request");
  214.                 result = paramErr;
  215.             }
  216.         }
  217.         else
  218.         {
  219.             Panic("\pDRVRPrime: Globals aren't initialized");
  220.             result = nsDrvErr;
  221.         }
  222.     }
  223.     else
  224.     {
  225.         Panic("\pDRVRPrime: No dCtlStorage");
  226.         result = notOpenErr;
  227.     }
  228.     
  229.     return (result);
  230. }
  231.  
  232. /*****************************************************************************/
  233.  
  234. pascal OSErr DRVRControl (ParmBlkPtr pb, DCtlPtr dce)
  235. {
  236.     DrvrGlobals       *globe;
  237.     OSErr            result = controlErr;
  238.     long            size;
  239.     long            i;
  240.     
  241.     if (dce->dCtlStorage)
  242.     {
  243.         globe = (DrvrGlobals *)dce->dCtlStorage;
  244.         
  245.         /* Accept only setGlobalsCC call, before the globals are initialized */
  246.         if (pb->cntrlParam.csCode == setGlobalsCC)
  247.         {
  248.             /* Initialize DrvrGlobals */
  249.             BlockMoveData( *(Ptr *)pb->cntrlParam.csParam,(Ptr)globe, sizeof(DrvrGlobals));
  250.             result = noErr;
  251.         }
  252.         else if (globe->driveNumber != 0)
  253.         {
  254.             switch(pb->cntrlParam.csCode)
  255.             {
  256.                 case killIOCC:
  257.                     /* What's there to kill?  A BlockMove? sure...  */
  258.                     /* We call Panic in this example; a real driver */
  259.                     /* would do something more reasonable.          */
  260.                     Panic("\pDRVRControl: KillIO on Ram Disk?");
  261.                     break;
  262.                 
  263.                 case verifyDiskCC:
  264.                     result = noErr;
  265.                     break;
  266.                 
  267.                 case formatDiskCC:
  268.                     /* zero out ram disk memory */
  269.                     size = globe->ramSize / 4;
  270.                     for (i = 0 ; i < size; i++)
  271.                         ((long *)globe->ramDisk)[i] = 0;
  272.                     result = noErr;
  273.                     break;
  274.                         
  275.                 case ejectDiskCC:
  276.                     // From Martin Minow's SCSI disk sample:
  277.                     // Certain old SFGetFile calls (System 4.1?) will eject
  278.                     // disks which are marked as non-ejectable (such as this one)
  279.                     // If that happens, we need to issue a disk insert event
  280.                     // to remount the disk
  281.                     PostEvent(diskEvt, globe->driveNumber);
  282.                      break;
  283.                             
  284.                 case physicalIconCC:
  285.                     /* return pointer to icon and where string */
  286.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->physicalIcon;
  287.                     result = noErr;
  288.                     break;
  289.                 
  290.                 case mediaIconCC:
  291.                     /* return pointer to icon and where string */
  292.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->mediaIcon;
  293.                     result = noErr;
  294.                     break;
  295.     
  296. // When a HFS volume is mounted, the File Manager calls the disk driver
  297. // with a "Return Drive Info" _Control call (csCode=23). Then if there
  298. // are no errors, it looks at the low-byte (bits 0-7) of csParam to see
  299. // if the drive type is ramDiskType (16, $10) or romDiskType (17, $11)
  300. // and if so, vcbAtDontCache is set in vcbAtrb.
  301. // 
  302. // You shouldn't normally have to mess with the vcbAtDontCache bit in the
  303. // vcbAtrb. If you've written a RAM or ROM disk and you want the cache to
  304. // be bypassed, you only need to support _Control csCode 23 and say
  305. // you're a RAM or ROM disk. Other disk drivers probably should not mess
  306. // with the vcbAtDontCache bit because any improvements we make to the
  307. // File Manager cache will be lost on those drives (and we'll have to say
  308. // so when customers ask why our improvements didn't help their drives).
  309. //
  310. // See the Inside Macintosh:Files Errata technote for a discussion of this.
  311.                 case driveInfoCC:
  312.                     /*  high word (bytes 2 & 3) clear  */
  313.                     /*  byte 1 = primary + fixed media + internal  */
  314.                     /*  byte 0 = drive type (0x10 = RAM disk)  */
  315.                     *(unsigned long *)pb->cntrlParam.csParam = 0x00000410;
  316.                     result = noErr;
  317.                     break;
  318.                 
  319.                 case 24:    /* ••• Return SCSI csCode Partition Size */
  320.                     *(unsigned long *)pb->cntrlParam.csParam = globe->ramSize >> 9;
  321.                     result = noErr;
  322.                     break;
  323.     
  324.                 case accRun:
  325.                     result = noErr;
  326.                     break;
  327.                 
  328.                 case kDriverConfigureCode:
  329.                     switch ( ((DriverConfigParam *)pb)->driverConfigureSelector )
  330.                     {
  331.                         case kdcFlush:
  332.                             globe->driveNeedsFlush = false;
  333.                             result = noErr;
  334.                             break;
  335.                         
  336.                         default:
  337.                             break;
  338.                     }
  339.                     break;
  340.                 
  341.                 default:
  342.                     Panic("\pUnrecognized control call");
  343.                     break;
  344.             }
  345.         }
  346.         else
  347.         {
  348.             Panic("\pDRVRControl: Globals not initialized");
  349.         }
  350.     }
  351.     else
  352.     {
  353.         Panic("\pDRVRControl: No dCtlStorage");
  354.         result = notOpenErr;
  355.     }
  356.         
  357.     return (result);
  358. }
  359.  
  360. /*****************************************************************************/
  361.  
  362. pascal OSErr DRVRStatus (ParmBlkPtr pb, DCtlPtr dce)
  363. {
  364.     DrvrGlobals            *globe;
  365.     OSErr                result = statusErr;
  366.     DrvSts                *driveStats;
  367.     DrvQElPtr            driveQEl;
  368.     DriverGestaltSyncResponse syncResponse;
  369.     NumVersion            versResponse;
  370.     
  371.     if (dce->dCtlStorage)
  372.     {
  373.         globe = (DrvrGlobals *)dce->dCtlStorage;
  374.     
  375.         /* Accept only getGlobalsSC call, before the globals are initialized */
  376.         if (pb->cntrlParam.csCode == getGlobalsSC)
  377.         {
  378.             *(long *)pb->cntrlParam.csParam = globe->ramSize;
  379.             if (globe->ramSize == 0)
  380.             {
  381.                 Panic("\pDRVRStatus: ramSize is zero");
  382.             }
  383.             result = noErr;
  384.         }
  385.         else if (globe->driveNumber != 0)
  386.         {
  387.             switch(pb->cntrlParam.csCode)
  388.             {
  389.                 case driveStatusSC:
  390.                     if (pb->cntrlParam.ioVRefNum != globe->driveNumber)
  391.                         break;
  392.                     
  393.                     /* Drive Stats... */
  394.                     driveStats = (DrvSts *)pb->cntrlParam.csParam;
  395.                     driveStats->track        = 0;    /* not applicable */
  396.                     driveStats->writeProt    = 0;    /* write enabled */
  397.                     driveStats->diskInPlace    = 0x08;    /* non-ejectable */
  398.                     driveStats->installed    = 1;    /* drive installed */
  399.                     driveStats->sides        = 0;    /* not applicable */
  400.                     driveStats->twoSideFmt    = 0;    /* not applicable */
  401.                     driveStats->needsFlush    = 0;    /* not applicable */
  402.                     driveStats->diskErrs    = 0;    /* not applicable */
  403.                     
  404.                     /* Copy qLink through dQFSID from our DrvQEl */
  405.                     driveQEl = (DrvQElPtr)(GetDrvQHdr()->qHead);
  406.                     while(driveQEl != nil)
  407.                     {
  408.                         if (driveQEl->dQDrive == globe->driveNumber)
  409.                         {
  410.                             driveStats->qLink = driveQEl->qLink;
  411.                             driveStats->qType = driveQEl->qType;
  412.                             driveStats->dQDrive = driveQEl->dQDrive;
  413.                             driveStats->dQRefNum = driveQEl->dQRefNum;
  414.                             driveStats->dQFSID = driveQEl->dQFSID;
  415.     
  416.                             break; /* while(driveQEl != nil) */
  417.                         }
  418.                         driveQEl = (DrvQElPtr)(driveQEl->qLink);
  419.                     }
  420.                     
  421.                     result = noErr;
  422.                     break;
  423.                 
  424.                 case kDriverGestaltCode:
  425.                     /*  We only support some information calls.  A real driver */
  426.                     /*  would support more of these calls, as defined in the */
  427.                     /*  Designing PCI Cards & Drivers document */
  428.                     switch ( ((DriverGestaltParam *)pb)->driverGestaltSelector )
  429.                     {
  430.                         case kdgSync:
  431.                             syncResponse.behavesSynchronously = true;    
  432.                             ((DriverGestaltParam *)pb)->driverGestaltResponse = 
  433.                                         *(unsigned long *)&syncResponse;
  434.                             result = noErr;
  435.                             break;
  436.                                                     
  437.                         case kdgFlush:
  438.                             {
  439.                                 GetDriverGestaltFlushResponse((DriverGestaltParam *)pb)->canFlush = true;
  440.                                 GetDriverGestaltFlushResponse((DriverGestaltParam *)pb)->needsFlush = globe->driveNeedsFlush;    
  441.                                 result = noErr;
  442.                             }
  443.                             break;
  444.                                                     
  445.                         case kdgVersion:
  446.                             versResponse = globe->driverVersion;
  447.                             
  448.                             ((DriverGestaltParam *)pb)->driverGestaltResponse = 
  449.                                         *(unsigned long *)&versResponse;
  450.                             result = noErr;
  451.                             break;
  452.                         default:
  453.                             break;
  454.                         }
  455.                     break;
  456.                         
  457.                 default:
  458.                     break;
  459.             }
  460.         }
  461.         else
  462.         {
  463.             Panic("\pDRVRStatus: Globals not initialized");
  464.         }
  465.     }
  466.     else
  467.     {
  468.         Panic("\pDRVRStatus: No dCtlStorage");
  469.         result = notOpenErr;
  470.     }
  471.  
  472.     return (result);
  473. }
  474.  
  475. /*****************************************************************************/
  476.  
  477. pascal OSErr DRVRClose (ParmBlkPtr pb, DCtlPtr dce)
  478. {
  479.     DrvrGlobals    *globe;
  480.  
  481. #pragma unused (pb)
  482.         
  483.     if (dce->dCtlStorage)
  484.     {
  485.         globe = (DrvrGlobals *)dce->dCtlStorage;
  486.         
  487.         if (globe->ramDisk)
  488.             DisposePtr(globe->ramDisk);
  489.         
  490.         DisposePtr((Ptr)dce->dCtlStorage);
  491.     }
  492.     
  493.     return (noErr);
  494. }
  495.